package com.sanerzone.smscenter.common.utils;

import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Properties;
 
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Message;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.SendFailedException;
 
import javax.mail.Authenticator;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sanerzone.jeebase.modules.sys.entity.Dict;
import com.sanerzone.jeebase.modules.sys.utils.DictUtils;

public class EmailUtil {
     
    private final static String default_charset = "UTF-8";
     
    public static enum EncryptionTypes{
        Default, TLS, SSL
    }
     
    static final Log logger = LogFactory.getLog(EmailUtil.class);
     
    private String mail_host = "";
    private int mail_port = 25;
    private int encryptionType = EncryptionTypes.Default.ordinal();
    private boolean auth = false;
    private String mail_host_account = "";
    private String mail_host_password = "";
    private boolean isHtml = false;
 
    public EmailUtil(String mail_host){
        this.mail_host = mail_host;
    }   
     
    public EmailUtil(String mail_host, boolean auth, String account, String password){
        this(mail_host, 25, EncryptionTypes.Default.ordinal(), auth, account, password);
    }
     
    public EmailUtil(String mail_host,int mail_port, int encryptionType, boolean auth, String account, String password){
        this.mail_host = mail_host;
        this.mail_port = mail_port;
        this.encryptionType = encryptionType;
        this.auth = auth;
        this.mail_host_account = account;
        this.mail_host_password = password;
    }
     
    public EmailUtil(String mail_host, boolean auth, String account, String password, boolean isHtml){
        this(mail_host, 25, EncryptionTypes.Default.ordinal(), auth, account, password, isHtml);
    }
     
    public EmailUtil(String mail_host,int mail_port, int encryptionType, boolean auth, String account, String password, boolean isHtml){
        this.mail_host = mail_host;
        this.mail_port = mail_port;
        this.encryptionType = encryptionType;
        this.auth = auth;
        this.mail_host_account = account;
        this.mail_host_password = password;
        this.isHtml = isHtml;
    }
 
    /**
     * Send email to a single recipient or recipient string.
     * 
     * @param senderAddress
     *            the sender email address
     * @param senderName
     *            the sender name
     * @param receiverAddress
     *            the recipient email address
     * @param sub
     *            the subject of the email
     * @param msg
     *            the message content of the email
     */
    public void sendEmail(String senderAddress,
            String senderName, String receiverAddress, String sub, String msg)
            throws Exception {
        String[] address = receiverAddress.split(";");
        List recipients = new ArrayList(); 
        for(int i=0;i<address.length;i++){
            if(address[i].trim().length()>0){
                recipients.add(address[i]);
            }
        }
 
        this.sendEmail(senderAddress, senderName, recipients, sub, msg);
    }
     
    public void sendEmail(String senderAddress,
            String senderName, List recipients, String sub, String msg)
            throws SendFailedException {
        this.sendEmail(senderAddress, senderName, recipients, sub, msg, null);
    }
     
    public void sendEmail(String senderAddress,
            String senderName, String receiverAddress, String sub, String msg, Collection attachments)
            throws Exception {
        String[] address = receiverAddress.split(",");
        List recipients = new ArrayList(); 
        for(int i=0;i<address.length;i++){
            if(address[i].trim().length()>0){
                recipients.add(address[i]);
            }
        }
 
        this.sendEmail(senderAddress, senderName, recipients, sub, msg, attachments);
    }
 
    /**
     * Send email to a list of recipients.
     * @param senderAddress
     *            the sender email address
     * @param senderName
     *            the sender name
     * @param recipients
     *            a list of receipients email addresses
     * @param sub
     *            the subject of the email
     * @param msg
     *            the message content of the email
     * @param attachments
     *            attachments list of the email
     */
    public void sendEmail(String senderAddress,
            String senderName, List recipients, String sub, String msg, Collection attachments)
            throws SendFailedException {
         
        logger.debug("mail subject: "+sub
                +" mail_port: "+this.mail_port
                +" encryptionType: "+this.encryptionType
                +" auth: "+this.auth
                +" mail_host_account: "+this.mail_host_account
                +" mail_host_password: "+this.mail_host_password);
         
        Transport transport = null;
 
        try {
             
            Properties props = this.getProperties();
             
            Session session = this.getSession(props);
             
            MimeMessage message = new MimeMessage(session);
 
            if(this.getDefaultIsHtml()){
                message.addHeader("Content-type", "text/html");
            }else{
                message.addHeader("Content-type", "text/plain");
            }
             
            message.setSubject(sub,default_charset);
            message.setFrom(new InternetAddress(senderAddress, senderName));
 
            for (Iterator it = recipients.iterator(); it.hasNext();) {
                String email = (String) it.next();
                message.addRecipients(Message.RecipientType.TO, email);
            }
             
            Multipart mp = new MimeMultipart();
             
            //content
            MimeBodyPart contentPart = new MimeBodyPart();
             
            if(this.getDefaultIsHtml()){
                contentPart.setContent("<meta http-equiv=Content-Type content=text/html; charset="+default_charset+">"+msg,"text/html;charset="+default_charset);
            }else{
                contentPart.setText(msg,default_charset);
            }
             
            mp.addBodyPart(contentPart);
             
            //attachment
            if(attachments!=null){
                MimeBodyPart attachPart;
                for(Iterator it = attachments.iterator(); it.hasNext();){
                    attachPart = new MimeBodyPart();
                    FileDataSource fds = new FileDataSource(it.next().toString().trim());
                    attachPart.setDataHandler(new DataHandler(fds));
                    if(fds.getName().indexOf("$")!=-1){
                        attachPart.setFileName(fds.getName().substring(fds.getName().indexOf("$")+1,fds.getName().length()));
                    }else{
                        attachPart.setFileName(fds.getName());
                    }
                    mp.addBodyPart(attachPart);
                }
                 
            }
             
            message.setContent(mp);
             
            message.setSentDate(new Date());
             
            if(this.getDefaultEncryptionType() == EncryptionTypes.SSL.ordinal()){
                Transport.send(message);
            }else{
                transport = session.getTransport("smtp");
                 
                transport.connect(this.mail_host,
                        this.mail_port,
                        this.mail_host_account,
                        this.mail_host_password);
                 
                transport.sendMessage(message, message.getAllRecipients());             
            }
 
        } catch (Exception e) {
            logger.error("send mail error", e);
            throw new SendFailedException(e.toString());
        } finally{
            if(transport!=null){
                try{
                    transport.close();
                }catch(Exception ex){
                }
            }
        }
    }
     
    private Properties getProperties(){
         
        Properties props = System.getProperties();
         
        int defaultEncryptionType = this.getDefaultEncryptionType();
         
        if(defaultEncryptionType == EncryptionTypes.TLS.ordinal()){
            props.put("mail.smtp.auth", String.valueOf(this.auth));
            props.put("mail.smtp.starttls.enable", "true");     
        }else if(defaultEncryptionType == EncryptionTypes.SSL.ordinal()){
            props.put("mail.smtp.host", this.mail_host);
            props.put("mail.smtp.socketFactory.port", this.mail_port);
            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");           
            props.put("mail.smtp.debug", "true");           
            props.put("mail.smtp.auth", String.valueOf(this.auth));
            props.put("mail.smtp.port", this.mail_port);
        }else{
            props.put("mail.smtp.host", this.mail_host);
            props.put("mail.smtp.auth", String.valueOf(this.auth));             
        }
 
        return props;
    }
     
    private Session getSession(Properties props){
        Session session = null;
         
        if(this.getDefaultEncryptionType() == EncryptionTypes.TLS.ordinal()){
            session = Session.getInstance(props);
        }else if(this.getDefaultEncryptionType() == EncryptionTypes.SSL.ordinal()){
            session = Session.getInstance(props, new MyAuthenticator(this.mail_host_account, this.mail_host_password));
        }else{
            session = Session.getDefaultInstance(props,null);       
        }
         
        return session;
    }
     
    private boolean getDefaultIsHtml(){
        boolean rst = this.isHtml;  
        return rst;
    }
     
    private class MyAuthenticator extends Authenticator{
        String user;
        String password;
        public MyAuthenticator(){
             
        }
         
        public MyAuthenticator(String user, String password){
            this.user = user;
            this.password = password;
        }
         
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(this.user, this.password);
        }
    }
     
    /**
     * get default encryption type,
     * for 465, SSL
     * for 587, TLS
     * @return
     */
    private int getDefaultEncryptionType(){
        int rst = this.encryptionType;
        if(this.encryptionType == EncryptionTypes.Default.ordinal()){
            if(this.mail_port==465){
                rst = EncryptionTypes.SSL.ordinal();
            }else if(this.mail_port==587){
                rst = EncryptionTypes.TLS.ordinal();
            }
        }
     
        return rst;
    }
     
    public static void main(String[] args){
         
        System.out.println("EncryptionTypes.SSL.ordinal(): "+EncryptionTypes.SSL.ordinal());
         
        EmailUtil email = new EmailUtil("smtp.exmail.qq.com", 465, 0, true, "xurui@konsone.com","2380915Xu",true);
        try{
            email.sendEmail(
                    "xurui@konsone.com",
                    "企业彩秀",
                    "316175992@qq.com",
                    "彩信审核通知",
                    "<html><body><font color='red'>您有待审彩信，主题: 测试彩信 ,请登录<a href=\"http://114.55.90.98:8800/\">企业彩秀平台</a>进行审核。</font></body></html>",
                    null);
            System.out.println("send out successfully");
        }catch(Exception ex){
            ex.printStackTrace();
            System.out.println("send fail");
        }
         
    }
    
    /**
     * 审核短信内容邮件发送
     * @see [类、类#方法、类#成员]
     */
    public static void CheckSmssendEmail(String content)
    {
        EmailUtil email = new EmailUtil("smtp.exmail.qq.com", 465, 0, true, "xurui@konsone.com", "2380915Xu", true);
        try
        {
        	List<Dict> list = DictUtils.getDictList("warnmail_address");
        	StringBuilder toAddress = new StringBuilder();
        	for(Dict item : list) {
        		toAddress.append(item.getValue()).append(",");
        	}
            email.sendEmail("xurui@konsone.com",
            	"宽信互联",
                toAddress.toString(), //"guorui_xu@qq.com,7552551@qq.com,447212972@qq.com,13666672546@139.com",
                "短信内容审核",
                "<html><body><font color='red'>" + content + ",请登录<a href=\"http://sms.konsone.com/\">宽信互联服务平台</a>进行处理。</font></body></html>",
                null);
            System.out.println("审核短信内容 send out successfully");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            System.out.println("审核短信内容 send fail");
        }
    } 
     
}
